import { ClickDetector } from "./click_detector";
import { Signal } from "./signal";

export class FormElement{
  constructor(id, label){
    this.id = id;
    this.label = label;

    this.valueChosen = new Signal();
  }

  getHtml(){
    abstract;
    return '';
  }

  /**
   * 
   * @param {HTMLElement} parent 
   * @returns 
   */
  getFormElement(parent){
    return parent.querySelector(`[data-formid='${this.id}']`);
  }

  bindEvents(parent, clickTrackers){
    abstract;
  }

  focus(){}

  isValid(){
    return true;
  }

  getValue(){
    abstract;
  }
}

export class FormElementInput extends FormElement{
  constructor({ id, label = null, placeholder = '', defaultValue = '', inputType = 'text', validator = null }){
    super(id, label)
    this.placeholder = placeholder;
    this.defaultValue = defaultValue;
    this.inputType = inputType;
    this.validator = validator;

    this.element = null;
  }

  getHtml(){
    let classes = [];
    let inputType = 'text';
    let maxlength = 256;
    switch(this.inputType){
      case 'text':{
        classes.push('input-text')
        break;
      }
      case 'email': {
        classes.push('input-email')
        inputType = 'email'
        break;
      }
      case 'password': {
        classes.push('input-password');
        inputType = 'password';
        break;
      }
      case 'token': {
        classes.push('input-token');
        inputType = 'text';
        maxlength = 4;
        break;
      }
    }

    return `
      <div class="formElement input">
        ${this.label ? `<label>${this.label}</label>` : ""}
        <input
          type="${inputType}"
          value="${('' + this.defaultValue).replace(/["\\]+/gi, "")}"
          maxlength="${maxlength}"
          autocomplete="off"
          autocorrect="off"
          autocapitalize="off"
          spellcheck="false"
          class="${classes.join(" ")}"
          placeholder="${('' + this.placeholder).replace(/["\\]+/gi, "")}"
          data-formId="${this.id}">
      </div>
    `
  }

  bindEvents(parent, clickTrackers){
    this.element = this.getFormElement(parent);
    this.element.addEventListener('input', event => this.updateErrorState());
    this.updateErrorState();
  }

  updateErrorState(){
    this.element.classList.toggle('errored', !this.isValid());
  }

  isValid(){
    return !this.validator || this.validator(this.element.value);
  }

  getValue(){
    return this.element.value;
  }

  setValue(value){
    this.element.value = value;
    this.updateErrorState();
  }

  focus(){
    this.element.focus();
    this.element.select();
  }
}

export class FormElementCheckbox extends FormElement{
  constructor({ id, label, defaultValue = true }){
    super(id, label);
    this.defaultValue = defaultValue;
    this.value = this.defaultValue;

    this.element = null;
  }

  getHtml(){
    return `
      <div class="formElement checkBoxFormElem">
        ${this.label ? `<label>${this.label}</label>` : ""}
        <div class="checkbox ${this.defaultValue ? "checked" : ""}" data-formId='${this.id}'>
          <span class="knob"></span >
        </div>
      </div>
    `
  }

  bindEvents(parent, clickTrackers){
    this.element = this.getFormElement(parent);
    const detector = new ClickDetector(this.element, {
      preventDefault: false
    });
    clickTrackers.push(detector);
    detector.click.add(this.toggle, this);
  }

  getValue(){
    return this.value;
  }

  toggle(){
    this.value = !this.value;
    this.element.classList.toggle('checked', this.value);
  }
}